/*
 * The MIT License (MIT)
 *
 * Copyright (c) 2016 pjoc.pub, blademainer.
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in all
 * copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 * SOFTWARE.
 *
 */

package pub.pjoc.pay.channels.wechat.service;

import com.xiongyingqi.util.StringUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.Assert;
import pub.pjoc.pay.channels.wechat.util.WeixinPayUtils;
import pub.pjoc.pay.channels.wechat.vo.OrderCallBackRequest;
import pub.pjoc.pay.channels.wechat.vo.OrderRequest;
import pub.pjoc.pay.channels.wechat.vo.OrderResponse;
import pub.pjoc.pay.channels.wechat.vo.ReturnResult;

import java.io.IOException;
import java.io.InputStream;

/**
 * we chat channel service
 *
 * @author blademainer
 * @version 2016-08-02 14:20
 */
@Service
public class WeixinOrderService {
  private static final Logger logger = LoggerFactory
      .getLogger(WeixinOrderService.class);
  @Autowired
  private WeixinPayConfigInfo weixinPayConfigInfo;

  /**
   * request a new order.
   *
   * @param orderRequest {@link OrderRequest}
   * @return {@link OrderResponse}
   */
  public final OrderResponse requestOrder(OrderRequest orderRequest) {
    Assert.hasText(orderRequest.getBody(), "商品描述不能为空");
    Assert.isTrue(orderRequest.getTotalFee() != null && orderRequest
        .getTotalFee() > 0, "金额必须大于0");
    Assert.hasText(orderRequest.getTradeType(), "支付类型必须是: "
        + "JSAPI，NATIVE，APP");
    if (WeixinPayUtils.isNeedOpenId(orderRequest)) {
      Assert.hasText(orderRequest.getOpenId(), "openId不能为空");
    }

    orderRequest.setAppId(weixinPayConfigInfo.getAppId());
    orderRequest.setMchId(weixinPayConfigInfo.getPayMchId());

    String nonceStr = StringUtil.randomString(32);
    orderRequest.setNonceStr(nonceStr);

    String orderId = WeixinPayUtils.generateOrderId();
    orderRequest.setOutTradeNo(orderId);

    orderRequest.setNotifyUrl(weixinPayConfigInfo.getPayCallBackUrl());

    String payKey = weixinPayConfigInfo.getPayKey();
    //sign
    String sign = WeixinPayUtils.sign(orderRequest, payKey, "sign");
    orderRequest.setSign(sign);


    String orderRequestUrl = weixinPayConfigInfo.getOrderRequestUrl();
    try {
      InputStream inputStream = WeixinPayUtils.xmlHttpPostRequest(orderRequestUrl, orderRequest);
      OrderResponse orderResponse = WeixinPayUtils
          .parseOrderResponse(inputStream, payKey);
      if (logger.isDebugEnabled()) {
        logger.debug("Requesting a order by request: {} and get "
            + "response: {}", orderRequest, orderResponse);
      }
      return orderResponse;
    } catch (IOException e) {
      logger.error("Caught exception when requesting a order! message: "
          + e.getMessage(), e);
    }

    return null;
  }

  /**
   * do call back the response.
   *
   * @param callBackRequest {@link OrderCallBackRequest}
   * @return {@link ReturnResult}
   */
  public final ReturnResult doCallBack(OrderCallBackRequest callBackRequest) {
    Assert.notNull(callBackRequest, "回调通知为空");
    String payKey = weixinPayConfigInfo.getPayKey();
    String sign = WeixinPayUtils.sign(callBackRequest, payKey, "sign");
    if (sign == null || !sign.equals(callBackRequest.getSign())) {
      ReturnResult returnResult = new ReturnResult();
      returnResult.setReturnCode(ReturnResult.FAIL);
      returnResult.setReturnMsg("sign error");
      logger.error(
          "Doing call back... check sign error! "
              + "remote sign: {}, local sign: {}",
          callBackRequest.getSign(), sign);
      return returnResult;
    }
    ReturnResult returnResult = new ReturnResult();
    returnResult.setReturnCode(ReturnResult.SUCCESS);
    return returnResult;
  }


}
